#pragma once

#if defined(__cplusplus) && defined(__CUDACC__)

#include "builtin_types.h"
#include "host_defines.h"

#if !defined(__CUDACC_RTC__)
#include <string.h>
#include <time.h>

extern "C"
{
#endif /* !__CUDACC_RTC__ */
  extern _CRTIMP __host__ __device__ __device_builtin__ __cudart_builtin__ clock_t __cdecl clock(void) __THROW;
  extern __host__ __device__ __device_builtin__ __cudart_builtin__ void *__cdecl memset(void *, int, size_t) __THROW;
  extern __host__ __device__ __device_builtin__ __cudart_builtin__ void *__cdecl memcpy(void *, const void *, size_t) __THROW;
#if !defined(__CUDACC_RTC__)
}
#endif /* !__CUDACC_RTC__ */

#if defined(__CUDA_ARCH__)

#if defined(__CUDACC_RTC__)
inline __host__ __device__ void *operator new(size_t, void *p)
{
  return p;
}
inline __host__ __device__ void *operator new[](size_t, void *p) { return p; }
inline __host__ __device__ void operator delete(void *, void *) {}
inline __host__ __device__ void operator delete[](void *, void *) {}
#else /* !__CUDACC_RTC__ */
#ifndef __CUDA_INTERNAL_SKIP_CPP_HEADERS__
#include <new>
#endif

#if defined(__GNUC__)

#define STD \
  std::

#else /* __GNUC__ */

#define STD

#endif /* __GNUC__ */

extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new(STD size_t, void *) throw();
extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new[](STD size_t, void *) throw();
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *, void *) throw();
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *, void *) throw();
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *, STD size_t) throw();
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *, STD size_t) throw();
#endif /* __cplusplus >= 201402L  || (defined(_MSC_VER) && _MSC_VER >= 1900) */
#endif /* __CUDACC_RTC__ */

#if !defined(__CUDACC_RTC__)
#include <stdio.h>
#include <stdlib.h>
#endif /* !__CUDACC_RTC__ */

extern "C"
{
  extern

#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 3)))
      __host__ __device__ __device_builtin__ __cudart_builtin__ int __cdecl printf(const char *, ...) __THROW;
#else  /* newer glibc */
      __host__ __device__ __device_builtin__ __cudart_builtin__ int __cdecl printf(const char *, ...);
#endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) && ( (__GLIBC__ < 2) || ( (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 3) ) ) */

  extern _CRTIMP __host__ __device__ __cudart_builtin__ void *__cdecl malloc(size_t) __THROW;
  extern _CRTIMP __host__ __device__ __cudart_builtin__ void __cdecl free(void *) __THROW;

#if defined(_MSC_VER)
  extern __host__ __device__ __cudart_builtin__ void *__cdecl _alloca(size_t);
#endif
}

#if !defined(__CUDACC_RTC__)
#include <assert.h>
#endif /* !__CUDACC_RTC__ */

extern "C"
{
#if defined(__CUDACC_RTC__)
  extern __host__ __device__ void __assertfail(const char *__assertion,
                                               const char *__file,
                                               unsigned int __line,
                                               const char *__function,
                                               size_t charsize);
#elif defined(__GNUC__)
  extern __host__ __device__ __cudart_builtin__ void __assert_fail(
      const char *, const char *, unsigned int, const char *)
      __THROW;
#elif defined(_WIN32)
  extern __host__ __device__ __cudart_builtin__ _CRTIMP void __cdecl _wassert(
      const wchar_t *, const wchar_t *, unsigned);
#endif
}

#if defined(__CUDACC_RTC__)
#ifdef NDEBUG
#define assert(e) (static_cast<void>(0))
#else /* !NDEBUG */
#define __ASSERT_STR_HELPER(x) #x
#define assert(e) ((e) ? static_cast<void>(0)                           \
                       : __assertfail(__ASSERT_STR_HELPER(e), __FILE__, \
                                      __LINE__, __PRETTY_FUNCTION__,    \
                                      sizeof(char)))
#endif /* NDEBUG */
__host__ __device__ void *operator new(size_t);
__host__ __device__ void *operator new[](size_t);
__host__ __device__ void operator delete(void *);
__host__ __device__ void operator delete[](void *);
#if __cplusplus >= 201402L
__host__ __device__ void operator delete(void *, size_t);
__host__ __device__ void operator delete[](void *, size_t);
#endif /* __cplusplus >= 201402L */

#if __cplusplus >= 201703L
namespace std
{
  enum class align_val_t : size_t
  {
  };
}
__host__ __device__ void *__cdecl operator new(size_t sz, std::align_val_t) noexcept;
__host__ __device__ void *__cdecl operator new[](size_t sz, std::align_val_t) noexcept;
__host__ __device__ void __cdecl operator delete(void *ptr, std::align_val_t) noexcept;
__host__ __device__ void __cdecl operator delete[](void *ptr, std::align_val_t) noexcept;
__host__ __device__ void __cdecl operator delete(void *ptr, size_t, std::align_val_t) noexcept;
__host__ __device__ void __cdecl operator delete[](void *ptr, size_t, std::align_val_t) noexcept;
#endif /* __cplusplus >= 201703L */

#else /* !__CUDACC_RTC__ */
#if defined(__GNUC__)

#if (__cplusplus >= 201103L)
#define THROWBADALLOC
#else
#define THROWBADALLOC throw(STD bad_alloc)
#endif
#define __DELETE_THROW throw()

#else /* __GNUC__ */

#define THROWBADALLOC throw(...)

#endif /* __GNUC__ */

extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new(STD size_t) THROWBADALLOC;
extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new[](STD size_t) THROWBADALLOC;
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *) throw();
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *) throw();
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *, STD size_t) throw();
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *, STD size_t) throw();
#endif /* __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)   */

#if __cpp_aligned_new
extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new(STD size_t, std::align_val_t);
extern __host__ __device__ __cudart_builtin__ void *__cdecl operator new[](STD size_t, std::align_val_t);
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *, std::align_val_t) noexcept;
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *, std::align_val_t) noexcept;
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete(void *, STD size_t, std::align_val_t) noexcept;
extern __host__ __device__ __cudart_builtin__ void __cdecl operator delete[](void *, STD size_t, std::align_val_t) noexcept;
#endif /* __cpp_aligned_new */

#undef THROWBADALLOC
#undef STD
#endif /* __CUDACC_RTC__ */

#endif /* __CUDA_ARCH__ */

#endif /* __cplusplus && __CUDACC__ */

#if defined(__CUDACC_RTC__) && (__CUDA_ARCH__ >= 350)
#include "cuda_device_runtime_api.h"
#endif

#include "math_functions.h"
